var fs = require("fs");
var path = require("path");

/** 引入Excel文件处理模块 */
const xlsx = require('node-xlsx');

function getMatchingFilePaths(_path = "", includes, excludes) {
  var filePath = path.resolve(_path);
  const filePaths = []
  //调用文件遍历方法
  fileDisplay(filePath, filePaths, includes, excludes, _path);
  return filePaths
}

// 判断路径是否符合 includes  excludes
// fileMode 1 文件夹  2 文件
function verifyPath(fileMode, filePath = '', includes = '', excludes = '', _path = '') {
  let bool = true
  const includesReg = new RegExp(includes)
  const excludesReg = new RegExp(excludes)
  if (fileMode === 2) {
    if (includes) {
      bool = includesReg.test(filePath)
    }
  }
  if (fileMode === 1) {
    if (includes && includesReg.test(filePath)) {
      bool = true
    }
  }
  if (excludes && excludesReg.test(filePath)) {
    bool = false
  }
  return bool
}

/**
 * 文件遍历方法
 * @param filePath 需要遍历的文件路径
 * @param filePaths 文件路径
 */
function fileDisplay(filePath, filePaths = [], includes, excludes, _path) {
  if (!verifyPath(1, filePath, includes, excludes, _path)) return
  //根据文件路径读取文件，返回文件列表
  let files = fs.readdirSync(filePath)
  //遍历读取到的文件列表
  files.forEach(function(filename) {
    //获取当前文件的绝对路径
    var filedir = path.join(filePath, filename);
    //根据文件路径获取文件信息，返回一个fs.Stats对象
    var stats = fs.statSync(filedir);
    var isFile = stats.isFile(); //是文件
    var isDir = stats.isDirectory(); //是文件夹
    if (!verifyPath(isDir ? 1 : 2, filedir, includes, excludes, _path)) return
    if (isFile) {
      filePaths.push(filedir)
    }
    if (isDir) {
      fileDisplay(filedir, filePaths, includes, excludes, _path); //递归，如果是文件夹，就继续遍历该文件夹下面的文件
    }
  });
}

// 获取 所有文件匹配内容
function getMatchingData(regularList = [], pathList = [], _path = '') {
  let res = {}
  pathList.forEach(item => {
    const data = getMatchingDataInFile(regularList, item, _path)
    for (let key in data) {
      res[key] = {
        ...res[key],
        ...data[key]
      }
    }
  })
  return res
}

// 获取文件内匹配 数据
function getMatchingDataInFile(regularList = [], path = "", _path = "") {
  let res = {}
  const fileData = fs.readFileSync(path, 'utf-8')
  regularList.forEach(item => {
    const reg = new RegExp(item, 'gm')
    const matchData = fileData.match(reg)
    let curtPath = path.replace(_path, '')
    if (matchData && matchData.length) {
      res[item] = {}
      res[item][curtPath] = matchData.length
    }
  })
  return res || {}
}

// 保存数据到路径下，表格文件
function saveDataInPath(data = {}, path) {
  let matchData = []
  let headerStyle = {
    alignment: {
      horizontal: "center",// 水平居中
      vertical: "center",// 垂直居中
    }
  }
  for (let key in data) {
    let arr = []
    arr.push({v: key, s: headerStyle})
    arr.push({
      v: eval(Object.values(data[key]).join('+')),
      s: headerStyle
    })
    let info = ''
    for (let k in data[key]) {
      info += `${k} ${data[key][k]}\n`
    }
    arr.push(info)
    matchData.push(arr)
  }
  const xlsxData = [
    {
      name: '批量匹配结果',
      data: [
        [],
        [],
        [],
        [{v: '时间', s: headerStyle}, {v: new Date().toLocaleDateString(), s: headerStyle}],
        [{v: '匹配正则', s: headerStyle}, {v: '数量', s: headerStyle}, {v: '文件路径', s: headerStyle}],
        ...matchData,
      ]
    }
  ]
  let options = {
    '!cols': [
      {wpx: 200},
      {wpx: 120},
      {wpx: 540},
    ],
  }
  let filename = 'A-批量匹配结果.xlsx'
  /** 构建数据流 */
  const buffer = xlsx.build(xlsxData, options);
  /** 将数据写入 .xlsx */
  try {
    filename = `/A-批量匹配结果-${Date.now()}.xlsx`
    fs.writeFileSync(path + filename, buffer);
  } catch(error) {
    console.error(error)
  }
  return filename
}

// 主函数 入口
function FileMatching(regular = "", path = "", includes = "", excludes = "", outPath = "") {
  const regularList = regular.split("\n").map(i => i.trim())
  // 获取所有匹配路径 根据（path includes excludes）
  const filePaths = getMatchingFilePaths(path, includes, excludes)
  // 根据路径 匹配 获取匹配结果
  // 整合匹配结果
  let matchData = getMatchingData(regularList, filePaths, path)
  // 格式化 输出数据
  // 输出到指定文件
  const filename = saveDataInPath(matchData, outPath || path)
  matchData = {
    origin: matchData,
    filename
  }
  return matchData
}

export default FileMatching;
